package com.qinggeng.project.system.service.impl;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.qinggeng.common.constant.Constants;
import com.qinggeng.common.enums.CommonEnum;
import com.qinggeng.common.exception.CustomException;
import com.qinggeng.common.utils.DateUtils;
import com.qinggeng.common.utils.SecurityUtils;
import com.qinggeng.common.utils.StringUtils;
import com.qinggeng.common.utils.spring.SpringUtils;
import com.qinggeng.framework.redis.RedisCache;
import com.qinggeng.project.api.dto.DistributionPointDto;
import com.qinggeng.project.api.security.utils.ApiUtils;
import com.qinggeng.project.system.domain.DistributionPoint;
import com.qinggeng.project.system.domain.OrdersPoint;
import com.qinggeng.project.system.domain.OrdersRecord;
import com.qinggeng.project.system.domain.UserAddress;
import com.qinggeng.project.system.domain.json.PointNameConfig;
import com.qinggeng.project.system.domain.vo.DistributionPointVO;
import com.qinggeng.project.system.mapper.DistributionPointMapper;
import com.qinggeng.project.system.mapper.OrdersPointMapper;
import com.qinggeng.project.system.service.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.method.P;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.HashSet;
import java.util.List;
import java.util.Set;


/**
 * 配送点Service业务层处理
 *
 * @author qinggeng
 * @date 2020-06-16
 */
@Slf4j
@Service
public class DistributionPointServiceImpl implements IDistributionPointService {

    public static final String POINT_NAME_CONFIG_KEY="sys.point.name";

    public static final String POINT_SUFFIX_NAME_KEY="POINT_NAME_CONFIG_SUFFIX_NAME";

    public static final String POINT_DESCRIBE_KEY="POINT_NAME_CONFIG_DESCRIBE";
    @Resource
    private DistributionPointMapper distributionPointMapper;
    @Resource
    private OrdersPointMapper ordersPointMapper;
    @Autowired
    private IOrdersService ordersService;
    @Autowired
    private IOrdersRecordService ordersRecordService;
    @Resource
    private RedisCache redisCache;
    @Autowired
    private IOrdersPointService ordersPointService;
    @Autowired
    private IUserAddressService userAddressService;
    @Autowired
    private ISysConfigService sysConfigService;



    /**
     * 查询配送点
     *
     * @param id 配送点ID
     * @return 配送点
     */
    @Override
    public DistributionPoint selectDistributionPointById(Long id) {
        return distributionPointMapper.selectDistributionPointById(id);
    }

    /**
     * 查询配送点列表
     *
     * @param distributionPoint 配送点
     * @return 配送点
     */
    @Override
    public List<DistributionPoint> selectDistributionPointList(DistributionPoint distributionPoint) {
        return distributionPointMapper.selectDistributionPointList(distributionPoint);
    }

    /**
     * 新增配送点
     *
     * @param distributionPoint 配送点
     * @return 结果
     */
    @Override
    public int insertDistributionPoint(DistributionPoint distributionPoint) {
        distributionPoint.setShopId(SecurityUtils.getShopId().longValue());
        distributionPoint.setDelFalg("10");
        distributionPoint.setCreateBy(SecurityUtils.getUsername());
        distributionPoint.setCreateTime(DateUtils.getNowDate());
        return distributionPointMapper.insertDistributionPoint(distributionPoint);
    }

    /**
     * 修改配送点
     *
     * @param distributionPoint 配送点
     * @return 结果
     */
    @Override
    public int updateDistributionPoint(DistributionPoint distributionPoint) {
        distributionPoint.setUpdateBy(SecurityUtils.getUsername());
        distributionPoint.setUpdateTime(DateUtils.getNowDate());
        return distributionPointMapper.updateDistributionPoint(distributionPoint);
    }

    /**
     * 批量删除配送点
     *
     * @param ids 需要删除的配送点ID
     * @return 结果
     */
    @Override
    public int deleteDistributionPointByIds(Long[] ids) {
        return distributionPointMapper.deleteDistributionPointByIds(ids);
    }

    /**
     * 删除配送点信息
     *
     * @param id 配送点ID
     * @return 结果
     */
    @Override
    public int deleteDistributionPointById(Long id) {
        return distributionPointMapper.deleteDistributionPointById(id);
    }

    @Override
    public List<DistributionPoint> selectDistributionHandleList(DistributionPoint distributionPoint) {
        return distributionPointMapper.selectDistributionHandleList(distributionPoint);
    }

    @Override
    public DistributionPointDto selectDistributionPointDtoByShopId(Long shopId, Float lng, Float lat) {
        return distributionPointMapper.selectDistributionPointDtoByShopId(shopId,lng,lat);
    }

    @Override
    public DistributionPointDto selectDistributionPointDtoById(Long pointId, Float lng, Float lat) {
        return distributionPointMapper.selectDistributionPointDtoById(pointId,lng,lat);
    }

    @Override
    public List<DistributionPointDto> selectDistributionPointDtoList(DistributionPoint where) {
        return distributionPointMapper.selectDistributionPointDtoList(where);
    }

    @Override
    public int countAllPonitCount() {
        return distributionPointMapper.countAllPonitCount();
    }

    @Override
    public DistributionPoint selectPointByCourierId(Long courierId) {
        return distributionPointMapper.selectDistributionPointByCourierId(courierId);
    }

    @Override
    public int updatePointSetCourierId(Long pointId, Long courierId) {
        DistributionPoint point=selectDistributionPointById(pointId);
        if(point!=null){
            point.setCourierId(courierId);
            return distributionPointMapper.updateDistributionPoint(point);
        }
        return 0;
    }

    @Override
    public DistributionPoint selectDistributionPointByOrdersId(Long ordersId) {
        return distributionPointMapper.selectDistributionPointByOrdersId(ordersId);
    }

    @Override
    public List<DistributionPointVO> selectDistributionPointVOList(DistributionPoint where) {
        return distributionPointMapper.selectDistributionPointVOList(where);
    }

    @Override
    public DistributionPointDto getDistributionPointDtoNearest(Float lng, Float lat, Long shopId) {
        DistributionPoint where = new DistributionPoint();
        where.setLng(lng);
        where.setLat(lat);
        where.setShopId(shopId);
        where.setIsOpen("10");
        DistributionPointDto distributionPointDto = distributionPointMapper.selectMinDistanceDistributionPointDto(where);
        if(distributionPointDto == null){
            return null;
        }
        return distributionPointDto;
    }

    /**
     * 自提点一键收货
     * @param pointId
     * @return
     */
    @Override
    public Set<String> oneClickReceipt(String pointId) {
        String pastDate = DateUtils.getPastDate(1);
        List<OrdersRecord> ordersRecords = ordersRecordService.listOrdersRecordByPointIdAndRecordDate(Long.parseLong(pointId), pastDate);

        if (ordersRecords == null || ordersRecords.size() == 0){
            throw new CustomException("该自提点没有可以取货的订单");
        }
        //取货失败订单
        Set<String> failTake = new HashSet<>();
        for (OrdersRecord ordersRecord : ordersRecords) {
            try {

                //取货
                ordersService.discOrdersAckTake(ordersRecord.getOrdersNo(),ordersRecord.getUserId());
                //修改记录状态
                ordersRecordService.updateOrdersRecordSendStatus(ordersRecord.getId());
            } catch (Exception e) {
                failTake.add(ordersRecord.getOrdersNo());
                log.error("DistributionPointServiceImpl.oneClickReceipt(),取货失败 ordersNo={}",ordersRecord.getOrdersNo(),e);
            }
        }
        return failTake;
    }

    @Override
    public String getDistributionPointName(Long shopId,Float lng,Float lat){
        DistributionPointDto pointDto=this.systemSelectPoint(shopId,null,null,lng,lat);
        if(null==pointDto||StringUtils.isEmpty(pointDto.getPointName())){
            return null;
        }
        return pointDto.getPointNameWithoutSuffixName();
    }


    @Override
    public DistributionPointDto systemSelectPoint(Long shopId, Long pointId, Long addressId, Float lng, Float lat) {
        if(ApiUtils.getIsLogin()){
            if(pointId==null){
                //获取redis中用户选择过的配送点Id
                pointId=redisCache.getCacheObject(Constants.POINT_KEY+ApiUtils.getUserId());
            }
            if(pointId==null){
                //用户上一次下单的配送点Id
                OrdersPoint ordersPoint=ordersPointService.selectOrdersPointByUserId(ApiUtils.getUserId());
                pointId=ordersPoint!=null?ordersPoint.getPointId():null;
            }
        }
        DistributionPointDto pointDto = this.selectDistributionPointDtoById(pointId, lng, lat);
        if(null==pointDto||null==pointDto.getIsOpen()||!pointDto.getIsOpen().equals(CommonEnum.STATUS_10.getValue())){
            UserAddress userAddress=userAddressService.selectUserAddressById(addressId);
            if(userAddress==null){
                userAddress=new UserAddress(lng,lat);
            }
            return this.getDistributionPointDtoNearest(userAddress.getAddressLng(),userAddress.getAddressLat(),shopId);

        }
        if(ApiUtils.getIsLogin()){
            redisCache.setCacheObject(Constants.POINT_KEY+ApiUtils.getUserId(),pointDto.getId());
        }
        return pointDto;
    }

    private PointNameConfig getPointNameConfig(){
        String pointNameConfigJson= SpringUtils.getBean(ISysConfigService.class).getConfigValue(POINT_NAME_CONFIG_KEY);
        return JSONObject.parseObject(pointNameConfigJson,PointNameConfig.class);
    }

    public String getPointSuffixName(String defaultValue){
        String suffixName=redisCache.getCacheObject(POINT_SUFFIX_NAME_KEY);
        if(StringUtils.isNotEmpty(suffixName)){
            return suffixName;
        }
        try{
            PointNameConfig pointNameConfig=this.getPointNameConfig();
            redisCache.setCacheObject(POINT_SUFFIX_NAME_KEY,pointNameConfig.getSuffixName());
            return pointNameConfig.getSuffixName();
        }catch (Exception e){
            return defaultValue;
        }

    }

    public String getPointDescribe(String defaultValue){
        String describe=redisCache.getCacheObject(POINT_DESCRIBE_KEY);
        if(StringUtils.isNotEmpty(describe)){
            return describe;
        }
        try{
            PointNameConfig pointNameConfig=this.getPointNameConfig();
            redisCache.setCacheObject(POINT_DESCRIBE_KEY,pointNameConfig.getDescribe());
            return pointNameConfig.getDescribe();
        }catch (Exception e){
            return defaultValue;
        }

    }
}
